import datetime
import json
import random
import threading
import time

import requests

import libs.config as config
from libs.account import Account
from libs.game import _get_snapshot_all

from libs.scheduler_v2 import SchedulerV2, TaskStatus
from libs.task_helper import TaskHelper
from libs.trade_helper import TradeHelper
from webserver.app import app

scheduler = SchedulerV2()


def local_active_check():
    active_user_ids = scheduler.list_running_windows()

    # 查询每个用户最近一次的任务开始时间及状态
    user_latest_tasks = scheduler.get_user_latest_tasks()
    process_limits = config.get_process_limit()
    if 'total' in process_limits:
        total_process_limit = process_limits.get('total')
    else:
        total_process_limit = sum(process_limits.values())

    active_window_count = len(active_user_ids)
    for user_id in user_latest_tasks:
        latest_task = user_latest_tasks.get(user_id)
        status = latest_task.get('status')
        task_id = latest_task.get('task_id')
        if status == TaskStatus.RUNNING:
            if user_id not in active_user_ids:
                # 任务还在运行，但窗口关闭了,更新任务状态
                SchedulerV2().finish(task_id, TaskStatus.TERMINATED)
                print(f'terminate {user_id}')
        else:
            end_time_str = latest_task.get('end_time')
            if end_time_str is not None and user_id in active_user_ids:
                # 如果运行窗口数量大于process_limit.total,则马上关闭窗口
                if active_window_count > total_process_limit and user_id not in config.get_exclude_accounts():
                    scheduler.close_window(user_id)
                    active_window_count -= 1
                else:
                    end_time = datetime.datetime.strptime(end_time_str, '%Y-%m-%d %H:%M:%S')
                    end_seconds = (datetime.datetime.now() - end_time).total_seconds()
                    if end_seconds > 1200 and user_id not in config.get_exclude_accounts():
                        # 如果任务结束已超过20分钟，关闭未运行窗口
                        scheduler.close_window(user_id)
                        active_window_count -= 1


def energy_check():
    global last_check_time
    if last_check_time is not None:
        duration = (datetime.datetime.now() - last_check_time).seconds
        # 间隔超过1分钟
        if duration < 60:
            return

    last_check_time = datetime.datetime.now()
    try:
        snapshot_all = _get_snapshot_all()
        for uid in accounts:
            if int(uid) in config.get_exclude_accounts():
                continue
            account = accounts.get(uid)
            snapshot = snapshot_all.get(uid, {})
            energy = int(snapshot.get('energy', 1000))
            if 'shot_time' in snapshot:
                shot_time = datetime.datetime.strptime(snapshot.get('shot_time'), '%Y-%m-%d %H:%M:%S')
                delta_minutes = int((datetime.datetime.now() - shot_time).total_seconds() / 60)
                energy = energy + delta_minutes * 0.75

            # 收蜂蜜
            if energy >= 200:
                if not account.get('wine', True) and account.get('honey'):
                    task_id = scheduler.get_task_id(uid, f'honey.py')
                    next_schedule_time = scheduler.next_schedule_time(uid, task_id, 60 * 45)
                    if next_schedule_time is not None:
                        if task_id not in running_or_pending_task_ids:
                            delay_seconds = 0
                            if next_schedule_time > datetime.datetime.now():
                                delay_seconds = (next_schedule_time - datetime.datetime.now()).seconds
                            TaskHelper(uid).add_task('honey.py', delay_seconds=delay_seconds)

    except Exception as e:
        raise e
        pass


def init_tasks():
    global last_init_time
    if last_init_time is not None:
        duration = (datetime.datetime.now() - last_init_time).seconds
        # 间隔超过半小时
        if duration < 1800:
            return

    scheduler.logger.debug('# clear_data')
    # 清理过期务数据
    SchedulerV2.clear()
    TradeHelper.clear()
    scheduler.logger.debug('# init_tasks')
    last_init_time = datetime.datetime.now()
    delay = 0
    for user_id in accounts:
        if int(user_id) in config.get_exclude_accounts():
            continue

        account = accounts.get(user_id)

        if account.get('is_vip', False):
            # VIP领体力
            delay += 1
            if scheduler.get_task_id(user_id, 'charge') not in running_or_pending_task_ids:
                TaskHelper(user_id).charge(delay_seconds=delay, ignore_running=False)

        delay += 1
        if account.get('trade', True):
            if scheduler.get_task_id(user_id, 'trade_v3') not in running_or_pending_task_ids:
                TaskHelper(user_id).trade(delay_seconds=delay, ignore_running=False)
        delay += 1

        if account.get('wine', True):
            if scheduler.get_task_id(user_id, 'windmill') not in running_or_pending_task_ids:
                TaskHelper(user_id).windmill(delay_seconds=delay, ignore_running=False)


def run_flask_app():
    app.run(port=10086)


if __name__ == "__main__":
    # 启动web服务
    flask_thread = threading.Thread(target=run_flask_app)
    flask_thread.start()

    last_init_time = None
    last_check_time = None
    Account().init_from_env()
    running_or_pending_task_ids = []
    while True:
        accounts = config.get_accounts()
        running_or_pending_task_ids = scheduler.get_pending_and_running_task_ids()
        # 任务初始化
        init_tasks()
        # 检查体力将满的账号，执行消耗体力的任务
        energy_check()
        if not config.is_scheduler_running():
            scheduler.logger.debug('scheduler is terminated, take no action')
        else:
            scheduler.run()

        # 检查窗口状态
        local_active_check()
        run_duration = int(config.get_env('run_duration', 30))
        time.sleep(run_duration)
